import argparse
import inspect
import sys
import pytz
from datetime import datetime
from cowpy import cow
from pygments import highlight
from pygments.formatters import TerminalFormatter
from pygments.lexers import PythonLexer


class BaseAction(object):
    label: str
    text: str

    @classmethod
    def action(cls, text):
        return True


class HighlighAction(BaseAction):
    """Prints higligh by Python syntax."""

    label = 'highligh'

    @classmethod
    def action(cls, text):
        print(highlight(text, PythonLexer(), TerminalFormatter()))


class CowsayAction(BaseAction):
    """Prints how cow say youre text."""

    label = 'cowsay'

    @classmethod
    def action(cls, text):
        cheese = cow.Moose()
        msg = cheese.milk(text)
        print(msg)


class TimeAction(BaseAction):
    """Prints time in selected timezone."""

    label = 'time'

    @classmethod
    def action(cls, text):
        time_now = datetime.now()

        time_tz = time_now.astimezone(pytz.timezone(text))
        print(time_tz)


def select_action(action_name=None):
    # Action  selector
    # Returns dictionary label:Action
    # If labeled object found, return only selected action
    # if not found return None
    action_dict = dict()
    for _name, module_obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(module_obj):
            if module_obj.__base__ == BaseAction:
                if action_name and module_obj.label == action_name:
                    action_dict.update({action_name: module_obj})
                    return action_dict
                elif not action_name:
                    action_dict.update({module_obj.label: module_obj})
    return action_dict


def perform_action(command, text):
    obj_action_dict = select_action(command)

    if obj_action_dict:
        obj_action = obj_action_dict[command]  # match better
        obj_action.action(text)


def main():
    command_list = select_action()
    parser = argparse.ArgumentParser()
    commands = parser.add_subparsers(dest='command', required=True, metavar='command')

    for cmd in command_list.keys():
        commands.add_parser(cmd, help=command_list[cmd].__doc__)

    parser.add_argument('usertext', type=str, help='User string to process ')
    args = parser.parse_args()
    perform_action(args.command, args.usertext)


if __name__ == '__main__':
    main()
